<template>
  <uploader ref="uploader"
            :auto-start="false"
            :file-status-text="statusText"
            :options="options"
            class="chunk-uploader"
            @file-added="onFileAdded"
            @file-success="onFileSuccess"
  >
    <div>
      <div class="inner" ref="inner">
        <div class="icon">
          <i class="el-icon-upload2"></i>
        </div>
        <div class="title">
          将文件拖到此处，或<a>点击上传</a>
          <br>
          单文件大小不能超过800MB
        </div>
        <div class="decoration">
          支持上传.doc .pdf .ppt .txt .xls .mov .mp4等格式的文件
        </div>
      </div>
      <uploader-list></uploader-list>
    </div>
  </uploader>
</template>

<script>
import {mergeMultiple, multipartUpload} from "@/api/resource";

export default {
  name: 'ChunkUpload',
  data() {
    return {
      // 在 uploader 组件上会有 uploader 属性 指向的就是 Uploader 实例
      // 这里可以调用实例方法
      // https://github.com/simple-uploader/Uploader/blob/develop/README_zh-CN.md#方法
      
      options: {
        // 目标上传 URL，可以是字符串也可以是函数，如果是函数的话，则会传入 Uploader.File 实例、
        // 当前块 Uploader.Chunk 以及是否是测试模式，默认值为 '/'
        target: function (file, chunkFile, mode) {
          // 分块上传前每次都会进入到该方法
          const key = 'chunk_' + chunkFile.offset;// 键值 用于获取分块链接URL
          return file.chunkUrlData.chunks[key];
        },
        // 为每个块向服务器发出 GET 请求，以查看它是否已经存在。如果在服务器端实现，
        // 这将允许在浏览器崩溃甚至计算机重新启动后继续上传。(默认: true)
        testChunks: false,

        // 只能上传一个文件
        singleFile: true,
        // 分块时按照该值来分。最后一个上传块的大小是可能是大于等于1倍的这个值但是小于两倍的这个值大小，
        // 可见这个 Issue #51，默认 1*1024*1024。
        chunkSize: 5 * 1024 * 1024,
        // 强制所有块小于或等于 chunkSize。否则，最后一个块将大于或等于chunkSize。(默认: false)
        forceChunkSize: true,
        // 包含在带有数据的多部分 POST 中的额外参数。这可以是一个对象或一个函数。如果是一个函数，
        // 它将被传递一个 Uploader.File、一个 Uploader.Chunk 对象和一个 isTest 布尔值（默认值{}：）
        query: function (file, chunkFile, mode) {
          const data = {'partNumber': chunkFile.offset + 1};
          return data;
        },
        uploadMethod: 'PUT',
        //  当上传的时候所使用的是方式，可选 multipart、octet，默认 multipart，参考 multipart vs octet。
        // MiniO 的分片不能使用表单
        method: 'octet',
        //  处理请求参数，默认 function (params) {return params}，一般用于修改参数名字或者删除参数。0.5.2版本后，
        processParams: function (params) {
          return {};
        }
      },
      attrs: {
        accept: 'image/*'
      },
      statusText: {
        success: '成功了',
        error: '出错了',
        uploading: '上传中',
        paused: '暂停中',
        waiting: '等待中'
      }
      
    };
  },
  mounted() {
    this.$nextTick(() => {
      window.uploader = this.$refs.uploader.uploader;
      window.uploader.assignBrowse(this.$refs.inner, false, true)
      window.uploader.assignDrop(this.$refs.inner)
    });
  },
  methods: {
    async onFileAdded(file) {
      if(file.size>=800*1024*1024){
        this.$message.error('请上传800M以下的文件');
        
        file.ignored = true//文件过滤

      }
      
      await this.getChunkUploadUrl(file);
    },
    async getChunkUploadUrl(file) {
      const fileName = file.name; // 文件名
      const chunkSize = file.chunks.length; // 分片数
      // 请求后台返回每个分块的上传链接
      multipartUpload({
        objectName: fileName,
        chunkSize: chunkSize
      })
        .then(res => {
          file.chunkUrlData = res.data

          // this.$nextTick(() => window.uploader.resume())
        })
        .catch(e => {
          console.log(e);
        });
    },
    // 单个文件上传成功
    onFileSuccess(rootFile, file, message) {
      mergeMultiple({
        fileName: file.name,
        uploadId: file.chunkUrlData.uploadId
      })
        .then(res => {
          console.log(res)
          this.$emit('change', {
            fileName: file.name,
            uploadId: file.chunkUrlData.uploadId,
            url: res.data
          })
        })
    }
  }
};
</script>

<style lang="scss" scoped>
  .chunk-uploader {
    width: 100%;
    border: 1px dashed dodgerblue;
    cursor: pointer;
    padding: 20px 0 0;

    &:hover {
      background-color: #fafafa;
    }
    .icon > i {
      font-size: 68px;
      color: gray;
    }
    a {
      color: dodgerblue;
      margin: 0 4px;
    }
    .inner {
      text-align: center;
    }
    .decoration {
      margin-bottom: 20px;
    }
  }
</style>
